/*题目描述

设计单链表类，并基于单链表类实现栈类和队列类：

（1）设计学生信息类StudentRecord，要求包含公有数据成员：string stuName和int stuNo，设计用于输出学生信息的公有成员函数：void print，输出格式为：Name : stuName, Number : stuNo。

（2）设计学生链表的结点类StudentNode，要求包含公有数据成员：StudentRecord data和StudentNode* next。

（3）设计学生链表类LinkedList，要求定义头插入、头删除、尾插入、遍历等公有成员函数

。

（4）由LinkedList派生LinkedStack类，基于单链表类的功能实现压栈和出栈的成员函数：void Push(StudentRecord record)和bool Pop(StudentRecord& record)。

（5）由LinkedList派生LinkedQueue类，基于单链表类的功能实现入队和出队的成员函数：void EnQueue(StudentRecord record)和bool DeQueue(StudentRecord& record)。



在main函数中：

定义一个LinkedQueue类的对象queue和一个LinkedStack类的对象stack，并根据用户的输入分别对queue和stack作出相应的操作。
若为"Push", 则压栈；若为"EnQueue", 则入队；若为"Pop", 则出栈；若为"DeQueue", 则出队；若为"Exit"，则退出；若为其它，则给出提示信息"Input error!"。
入栈和入队时，输入学生姓名和学号。出栈和出队时，若非空，则输出被删除的学生信息；若栈空，则输出Stack is empty!"；若队空，则输出"Queue is empty!"。
输入

操作名；学生姓名，学号。
输出

删除的信息；提示信息。
样例输入

Push
ZhangSan 200905
Push
LiSi 200906
EnQueue
WangWu 200907
Pop
exit
Exit

样例输出

Name : LiSi, Number : 200906
Input error!

*/

#include <iostream>
#include <string>

using namespace std;

struct StudentNode;
class StudentRecord
{
	string stuName;
	int stuNo;
public:
	StudentRecord() {}
	StudentRecord(string stuName, int stuNo);
	void print();
	void setRecord(string stuName, int stuNo);
};

struct StudentNode
{
	StudentRecord data;
	StudentNode* next;
};

class LinkedList
{
public:
	StudentNode* CreatNode(StudentRecord data);
	void ListPushHead(StudentNode** pplist, StudentRecord data);
	void ListPushBack(StudentNode** pplist, StudentRecord data);
	bool ListPopHead(StudentNode** pplist);
	bool ListPopBack(StudentNode** pplist);
};

class LinkedStack : public LinkedList
{
	StudentNode* list_stack;
public:
	LinkedStack() :list_stack(NULL) {}
	void Push(StudentRecord record);
	bool Pop(StudentRecord& record);
};

class LinkedQueue : public LinkedList
{
	StudentNode* list_queue;
public:
	LinkedQueue() :list_queue(NULL) {}
	void EnQueue(StudentRecord record);
	bool DeQueue(StudentRecord& record);
};

int JudgeStatus(string arrstatus);
int main()
{
	LinkedQueue queue;
	LinkedStack stack;
	StudentRecord record;
	string arrstatus, stuName;
	int stuNo, status;

	for (;;) {
		cin >> arrstatus;
		status = JudgeStatus(arrstatus);
		switch (status)
		{
		case 0: {
			cin >> stuName >> stuNo;
			record.setRecord(stuName, stuNo);
			stack.Push(record);
		}
			  break;
		case 1: 
			stack.Pop(record);
			  break;
		case 2: {
			cin >> stuName >> stuNo;
			record.setRecord(stuName, stuNo);
			queue.EnQueue(record);
		}
			  break;
		case 3:
			queue.DeQueue(record);
			  break;
		case 4: exit(0);
			break;
		default:
			cout << "Input error!" << endl;
			break;
		}
	}
}

int JudgeStatus(string arrstatus)
{
	int status;
	if (arrstatus == "Push") status = 0;
	else if (arrstatus == "Pop") status = 1;
	else if (arrstatus == "EnQueue") status = 2;
	else if (arrstatus == "DeQueue") status = 3;
	else if (arrstatus == "Exit") status = 4;
	else status = 5;
	return status;
}

StudentRecord::StudentRecord(string stuName, int stuNo)
{
	this->stuName = stuName;
	this->stuNo = stuNo;
}
void StudentRecord::setRecord(string stuName, int stuNo)
{
	this->stuName = stuName;
	this->stuNo = stuNo;
}
void StudentRecord::print()
{
	cout << "Name: " << stuName << ", Number: " << stuNo << endl;
}

StudentNode* LinkedList::CreatNode(StudentRecord data)
{
	StudentNode* newnode = new StudentNode;
	if (newnode == NULL)
	{
		exit(-1);
	}
	newnode->data = data;
	return newnode;
}

void LinkedList::ListPushHead(StudentNode** pplist, StudentRecord data)
{
	StudentNode* head = *pplist;
	StudentNode* newnode = CreatNode(data);
	newnode->next = NULL;
	if (head == NULL)
	{
		*pplist = newnode;
	}
	else
	{
		while (head->next)
		{
			head = head->next;
		}
		head->next = newnode;
	}
}

void LinkedList::ListPushBack(StudentNode** pplist, StudentRecord data)
{
	StudentNode* newnode = CreatNode(data);
	if (!(*pplist))
	{
		*pplist = newnode;
	}
	else
	{
		newnode->next = *pplist;
		*pplist = newnode;
	}
}

bool LinkedList::ListPopBack(StudentNode** pplist)
{
	if (pplist) {
		StudentNode* head = *pplist;
		StudentNode* Pretail = NULL;
		if (head->next == NULL)
		{
			*pplist = NULL;
			return true;
		}
		else
		{
			while (head->next)
			{
				Pretail = head;
				head = head->next;
			}
			delete head;
			head = NULL;
			Pretail->next = NULL;
		}
		return true;
	}
	else {
		return false;
	}

}

bool LinkedList::ListPopHead(StudentNode** pplist)
{
	if (pplist) {
		StudentNode* tail = *pplist;
		*pplist = tail->next;
		delete tail;
		tail = NULL;
		return true;
	}
	else {
		return false;
	}

}

void LinkedStack::Push(StudentRecord record)
{
	this->ListPushBack(&list_stack, record);
}

bool LinkedStack::Pop(StudentRecord& record)
{
	if (list_stack) {
		list_stack->data.print();
		this->ListPopHead(&list_stack);
		return true;
	}
	else {
		cout << "Stack is empty!" << endl;
		return false;
	}
}

void LinkedQueue::EnQueue(StudentRecord record)
{
	this->ListPushHead(&list_queue, record);
}

bool LinkedQueue::DeQueue(StudentRecord& record)
{
	if (list_queue) {
		list_queue->data.print();
		this->ListPopHead(&list_queue);
		return true;
	}
	else {
		cout << "Queue is empty!" << endl;
		return false;
	}
}
